package client;

import entities.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Line2D;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.BorderFactory;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 *
 * @author casshern
 */
public class WorldPanel extends JPanel implements MouseListener {

    private ArrayList<GameObject> objects;
    private Client client;
    private Line2D[] gridX1, gridY1, gridX2, gridY2;
    private boolean showGrids;
    private GameObject selectedObj;
    private boolean isSelecting;
    private int selectX, selectY;
    private BottomPanel bottomPanel;
    private boolean buttonClicked;
    private BackgroundImage aaaa = new BackgroundImage(0, 0);

    public WorldPanel(Client client) {

        this.client = client;
        objects = new ArrayList<GameObject>();
        this.setPreferredSize(new Dimension(1000, 500));
        this.setBackground(Color.BLACK);
        this.setBorder(BorderFactory.createTitledBorder("Game Area"));
        this.addMouseListener(this);

        showGrids = false;

        gridX1 = new Line2D[19];
        gridY1 = new Line2D[19];
        gridX2 = new Line2D[19];
        gridY2 = new Line2D[19];

        for (int i = 0; i < 19; i++) {
            gridX1[i] = new Line2D.Double(50, 70 + i * 20, 450, 70 + i * 20);
            gridY1[i] = new Line2D.Double(70 + i * 20, 50, 70 + i * 20, 450);
            gridX2[i] = new Line2D.Double(550, 70 + i * 20, 950, 70 + i * 20);
            gridY2[i] = new Line2D.Double(570 + i * 20, 50, 570 + i * 20, 450);
        }
    }

    public void setBottomPanel(BottomPanel bottomPanel) {
        this.bottomPanel = bottomPanel;
    }

    public void gameUpdate(ArrayList<Property> properties) {
        objects.clear();
        for (int i = 1; i < properties.size(); i++) {
            int playerID = properties.get(i).getPlayerID();
            int type = properties.get(i).getType();
            int x = properties.get(i).getX();
            int y = properties.get(i).getY();
            int health = properties.get(i).getCurrentHealth();
            boolean alive = properties.get(i).isAlive();
            switch (type) {
                case GameObject.ASTEROID0:
                case GameObject.ASTEROID1:
                case GameObject.ASTEROID2:
                case GameObject.ASTEROID3:
                    objects.add(new Asteroid(type, x, y, health, alive));
                    break;
                case GameObject.ATTACK:
                    objects.add(new Attack(playerID, x, y, health, alive));
                    break;
                case GameObject.LASER:
                    objects.add(new Laser(playerID, x, y, health, alive));
                    break;
                case GameObject.MINER:
                    objects.add(new Miner(playerID, x, y, health, alive));
                    break;
                case GameObject.POWERSTATION:
                    objects.add(new PowerStation(playerID, x, y, health, alive));
                    break;
            }
        }
        repaint();
//        for (GameObject obj : objects) {
//            System.out.println(obj.getProperty().getX() + " " + obj.getProperty().getY());
//        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        aaaa.drawObject((Graphics2D) g);
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setColor(Color.white);
        int x, y, size;
        size = 400;
        y = 50;
        if (client.getID() == 1) {
            x = 50;
        } else {
            x = 550;
        }
        g2.drawRect(x, y, size, size);

        for (int i = 0; i < objects.size(); i++) {
            objects.get(i).drawObject(g2);
        }

        //=========================================================================
        //draw grid
        //=========================================================================
        if (showGrids) {
            //if iD =1
            g2.setColor(Color.white);
            if (client.getID() == 1) {
                for (int i = 0; i < gridX1.length; i++) {
                    g2.draw(gridX1[i]);
                    g2.draw(gridY1[i]);
                }
            } else {
                //if ID=2
                for (int i = 0; i < gridX2.length; i++) {
                    g2.draw(gridX2[i]);
                    g2.draw(gridY2[i]);
                }
            }
        }

        if (isSelecting && selectedObj != null) {
            bottomPanel.showObjInfo(selectedObj);
            int xx = selectedObj.getX();
            int yy = selectedObj.getY();
            int ss = selectedObj.getSize();
            g2.setColor(Color.red);
            g2.drawRect(xx, yy, ss, ss);
        }
    }

    public void clearSelectedObj() {
        isSelecting = false;
        selectedObj = null;
        repaint();
    }

    public void showObjInfo() {
        if (isSelecting) {
            if (selectObject(selectX, selectY)) {
                bottomPanel.showObjInfo(selectedObj);
            } else {
                isSelecting = false;
                client.getGameFrame().setInfoType(GameFrame.SHOW_GAME_INFO);
            }
        }
    }

    public boolean selectObject(int x, int y) {
        for (int i = 0; i < objects.size(); i++) {
            //Find the selected object
            if (objects.get(i).contains(x, y)) {
                selectedObj = objects.get(i);
                if (!selectedObj.isAlive()) {
                    selectedObj = null;
                    isSelecting = false;
                    client.getGameFrame().setInfoType(GameFrame.SHOW_GAME_INFO);
                    return false;
                }
                selectX = selectedObj.getX() + 5;
                selectY = selectedObj.getY() + 5;
                client.getGameFrame().setInfoType(GameFrame.SHOW_OBJ_INFO);
                bottomPanel.showObjInfo(selectedObj);
                return true;
            }
        }
        return false;
    }

    public void mouseClicked(MouseEvent e) {
        if (buttonClicked) {
            //When any button is clicked, send the position where the mouse is clicked in worldPanel
            //Release the clicked button
            bottomPanel.buttonRelease();
            //Release the selected object
            isSelecting = false;
            selectedObj = null;
            client.getGameFrame().setInfoType(GameFrame.SHOW_GAME_INFO);
            bottomPanel.showGameInfo();
            //Send the position
            try {
                client.send(e.getX() + "," + e.getY());
            } catch (IOException ex) {
                Logger.getLogger(WorldPanel.class.getName()).log(Level.SEVERE, null, ex);
                JOptionPane.showMessageDialog(this, "Something wrong with Network.");
                System.exit(1);
            }
        } else {
            //When no button is clicked, select object in worldPanel
            this.hideGrids();
            if (selectObject(e.getX(), e.getY())) {
                isSelecting = true;
                selectX = e.getX();
                selectY = e.getY();
                return;
            }
            //No object is selected
            //Release the selected object which was selected last time
            isSelecting = true;
            selectedObj = null;
            client.getGameFrame().setInfoType(GameFrame.SHOW_GAME_INFO);
            bottomPanel.showGameInfo();
        }
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void showGrids() {
        showGrids = true;
        repaint();

    }

    public void hideGrids() {
        showGrids = false;
        repaint();

    }

    public void setButtonClicked(boolean buttonClicked) {
        this.buttonClicked = buttonClicked;
    }
}
